package cn.cdm.controller;

import cn.cdm.config.UserArgumentResolver;
import cn.cdm.domain.MiaoshaUser;
import cn.cdm.redis.GoodsKey;
import cn.cdm.redis.RedisService;
import cn.cdm.service.GoodsService;
import cn.cdm.service.MiaoshaUserService;
import cn.cdm.vo.GoodsVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


@Controller
@RequestMapping("/goods")
public class GoodsController {
	private static Logger log = LoggerFactory.getLogger(GoodsController.class);

	@Autowired
	MiaoshaUserService userService;
	
	@Autowired
	RedisService redisService;
	
	@Autowired
	GoodsService goodsService;

	@Autowired
	ThymeleafViewResolver thymeleafViewResolver;

	/**
	 * jMeter并发测试：
	 * 5000个并发，循环了10次。总共是5万个请求
	 * QPS：1267（MySQL的负载飙升）  使用本机：689；671；757；705
	 *
	 *  MiaoshaUser对象会进入UserArgumentResolver类的入参检验功能
	 * @see cn.cdm.config.UserArgumentResolver
	 * @param model
	 * @param user
	 * @return
	 */
    @RequestMapping("/to_list") // todo 用户未登录成功的情况下,也可以访问该接口,后续可以设置拦截器:当用户直接访问商品列表但是未登录时,直接跳转到登录页面.
    public String list(Model model, MiaoshaUser user) {
    	log.debug("user: " + user);
    	model.addAttribute("user", user);
    	// 若该用户不存在，则需要登录成功后，才能查看商品列表页
		if(user == null) {
			log.info("秒杀用户不存在，返回登录页面");
			return "login";
		}
    	// 查询商品列表
    	List<GoodsVo> goodsList = goodsService.listGoodsVo();
    	model.addAttribute("goodsList", goodsList);
		log.debug("秒杀goodsList: " + goodsList);
		// 进入商品列表页面
        return "goods_list";
    }


	/*
	// 使用@CookieName注解的写法
	@RequestMapping("/to_list")
	public String list(HttpServletResponse response, Model model,
					   @CookieValue(value = MiaoshaUserService.COOKI_NAME_TOKEN, required = false)
							   String cookieToken,
	                   @RequestParam(value = MiaoshaUserService.COOKI_NAME_TOKEN, required = false)
								   String paramToken) {
		if (org.apache.commons.lang3.StringUtils.isEmpty(cookieToken) &&
				org.apache.commons.lang3.StringUtils.isEmpty(paramToken)) {
			log.info("该用户的sessionId不存在，故返回至登录界面");
			return "login";
		}
		// 优先获取手机端的cookie
		String token = org.apache.commons.lang3.StringUtils.isNotEmpty(paramToken) ? paramToken : cookieToken;
		MiaoshaUser user = userService.getByToken(response, token);
		// 将该用户对象，返回给thymeleaf模板，提供给前端使用
		model.addAttribute("user", user);

		return "goods_list";
	}
	*/


	/**
	 * 页面缓存
	 * 优化1：商品列表页面缓存到redis中
	 *
	 *  jMeter并发测试：
	 *  5000个并发，循环了10次
	 * 	QPS：2884（MySQL的负载很低）
	 */
    @RequestMapping("/to_list2")
	@ResponseBody
    public String list2(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user) {
    	log.debug("user: " + user);
    	model.addAttribute("user", user);
    	// 先取缓存
		String html = redisService.get(GoodsKey.goodList, "" , String.class);
		if(!StringUtils.isEmpty(html)){
			log.debug("取：秒杀goodsList在缓存中");
			return html;
		}

		// 查询商品列表，存储到model对象中
		List<GoodsVo> goodsList = goodsService.listGoodsVo();
		model.addAttribute("goodsList", goodsList);

		// 手动渲染Thymeleaf模板
		WebContext webContext = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
		html = thymeleafViewResolver.getTemplateEngine().process("goods_list2", webContext);
		if (org.apache.commons.lang3.StringUtils.isNotEmpty(html)) {
			// 将模板页面存入缓存，过期时间为300秒
			redisService.set(GoodsKey.goodList, "", html);
			log.debug("存：秒杀的商品列表goodsList放入缓存中");
		}

        return html;
    }


	/**
	 * URL缓存：针对不同的商品详情页
	 * @RequestParam("goodsId")long goodsId
	 * @param request
	 * @param response
	 * @param model
	 * @param user
	 * @param goodsId
	 * @return
	 */
    @ResponseBody
    @RequestMapping("/to_detail2/{goodsId}")
    public String detail2(HttpServletRequest request, HttpServletResponse response,Model model,MiaoshaUser user,
    		@PathVariable("goodsId")long goodsId) {
    	model.addAttribute("user", user);
		String html = redisService.get(GoodsKey.goodDetail, String.valueOf(goodsId), String.class);
		if(!StringUtils.isEmpty(html)){
			log.debug("取：秒杀goodsDetail在缓存中");
			return html;
		}
    	GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
    	log.debug("goods" + goods);
    	model.addAttribute("goods", goods);
		long startAt = goods.getStartDate().getTime();
    	long endAt = goods.getEndDate().getTime();
    	long now = System.currentTimeMillis();

    	// 秒杀的状态：0未开始，1秒杀进行中，2已结束
    	int miaoshaStatus = 0;
    	int remainSeconds = 0;
    	if(now < startAt ) {//秒杀还没开始，倒计时
    		miaoshaStatus = 0;
    		remainSeconds = (int)((startAt - now )/1000);
    	}else  if(now > endAt){//秒杀已经结束
    		miaoshaStatus = 2;
    		remainSeconds = -1;
    	}else {//秒杀进行中
    		miaoshaStatus = 1;
    		remainSeconds = 0;
    	}
    	model.addAttribute("miaoshaStatus", miaoshaStatus);
    	model.addAttribute("remainSeconds", remainSeconds);
		log.debug("开始存：秒杀goodsDetail放入缓存中");
		WebContext webContext = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
		html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", webContext);
		redisService.set(GoodsKey.goodDetail, String.valueOf(goodsId), html);
		log.debug("存：秒杀goodsDetail放入缓存中");
		return html;
    }

    @RequestMapping("/to_detail/{goodsId}")
    public String detail(Model model,MiaoshaUser user,
    		@PathVariable("goodsId")long goodsId) {
    	model.addAttribute("user", user);
    	GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
    	log.debug("" + goods);
    	model.addAttribute("goods", goods);

    	long startAt = goods.getStartDate().getTime();
    	long endAt = goods.getEndDate().getTime();
    	long now = System.currentTimeMillis();

    	int miaoshaStatus = 0;
    	int remainSeconds = 0;
    	if(now < startAt ) {//秒杀还没开始，倒计时
    		miaoshaStatus = 0;
    		remainSeconds = (int)((startAt - now )/1000);
    	}else  if(now > endAt){//秒杀已经结束
    		miaoshaStatus = 2;
    		remainSeconds = -1;
    	}else {//秒杀进行中
    		miaoshaStatus = 1;
    		remainSeconds = 0;
    	}
    	model.addAttribute("miaoshaStatus", miaoshaStatus);
    	model.addAttribute("remainSeconds", remainSeconds);
        return "goods_detail";
    }





    
}






































